# Copyright 2022 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@rules_python//sphinxdocs:sphinx_docs_library.bzl", "sphinx_docs_library")
load("//pw_build:compatibility.bzl", "incompatible_with_mcu")
load("//pw_build:merge_flags.bzl", "flags_from_dict")
load("//pw_build:pw_cc_binary.bzl", "pw_cc_binary")
load("//pw_build:pw_copy_and_patch_file.bzl", "pw_copy_and_patch_file")
load("//pw_toolchain/cc/current_toolchain:conditions.bzl", "if_compiler_is_clang")
load("//targets/rp2040:flash.bzl", "flash_rp2040", "flash_rp2350")
load("//targets/rp2040:transition.bzl", "RP2_SYSTEM_FLAGS", "rp2040_binary", "rp2350_binary")

package(
    default_visibility = ["//visibility:public"],
    features = ["-layering_check"],
)

licenses(["notice"])

config_setting(
    name = "pico_clang_build",
    constraint_values = [
        "//pw_build/constraints/chipset:rp2040",
    ],
    flag_values = {
        "@bazel_tools//tools/cpp:compiler": "clang",
    },
)

# This is an incomplete platform, do NOT try to pass this
# as a --platforms flag value. Use :rp2040 or :rp2350.
platform(
    name = "rp2_common",
    constraint_values = [
        "@freertos//:disable_task_statics",
        "freertos_config_cv",
        "//pw_build/constraints/chipset:rp2040",  # TODO: https://pwbug.dev/343487589 - Use Pico SDK constraints.
        "//pw_build/constraints/rtos:freertos",
        "//pw_cpu_exception:enabled",
        "//pw_interrupt_cortex_m:backend",
        "//pw_build/constraints/rust:no_std",
        "@platforms//os:none",
    ],
    flags = flags_from_dict(RP2_SYSTEM_FLAGS),
    visibility = ["//visibility:private"],
)

platform(
    name = "rp2040",
    constraint_values = [
        "@freertos//:port_ARM_CM0",
        "@pico-sdk//bazel/constraint:rp2040",
        # For toolchain selection.
        "@platforms//cpu:armv6-m",
        "//pw_build/constraints/arm:cortex-m0plus",
    ],
    flags = flags_from_dict({
        "@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT": package_relative_label(":rp2040_linker_script"),
    }),
    parents = [":rp2_common"],
)

platform(
    name = "rp2350",
    constraint_values = [
        "@freertos//:port_ARM_CM33_NTZ",
        "@pico-sdk//bazel/constraint:rp2350",
        # For toolchain selection.
        "@platforms//cpu:armv8-m",
        "//pw_build/constraints/arm:cortex-m33",
    ],
    flags = flags_from_dict({
        "@pico-sdk//bazel/config:PICO_DEFAULT_LINKER_SCRIPT": package_relative_label(":rp2350_linker_script"),
    }),
    parents = [":rp2_common"],
)

platform(
    name = "rp2040_pw_system_demo",
    flags = flags_from_dict({
        "@bazel_tools//tools/cpp:link_extra_libs": package_relative_label(":pre_init"),
    }),
    parents = [":rp2040"],
)

platform(
    name = "rp2350_pw_system_demo",
    flags = flags_from_dict({
        "@bazel_tools//tools/cpp:link_extra_libs": package_relative_label(":pre_init"),
    }),
    parents = [":rp2350"],
)

# These need to get linked into every `cc_binary` for the linker
# to succeed.
cc_library(
    name = "extra_platform_libs",
    deps = [
        "//pw_build:default_link_extra_lib",
        "//pw_tokenizer:linker_script",
        "@pico-sdk//src/rp2_common/pico_stdlib",
    ] + if_compiler_is_clang(
        [
            "//pw_libcxx",
            "@pico-sdk//src/rp2_common/pico_clib_interface:llvm_libc_interface",
        ],
        otherwise = [],
    ),
    alwayslink = 1,
)

alias(
    name = "pico_sdk_clib_select",
    actual = if_compiler_is_clang(
        "@pico-sdk//src/rp2_common/pico_clib_interface:llvm_libc_interface",
        otherwise = "@pico-sdk//src/rp2_common/pico_clib_interface:newlib_interface",
    ),
)

cc_library(
    name = "freertos_config",
    hdrs = [
        "config/FreeRTOSConfig.h",
    ],
    strip_include_prefix = "config",
    target_compatible_with = [":freertos_config_cv"],
    deps = [
        "//third_party/freertos:config_assert",
        "@pico-sdk//src/rp2_common/cmsis:cmsis_core",
    ],
)

constraint_value(
    name = "freertos_config_cv",
    constraint_setting = "@freertos//:freertos_config_setting",
)

cc_library(
    name = "unit_test_app",
    testonly = True,
    srcs = [
        "unit_test_app.cc",
    ],
    deps = [
        ":pre_init",
        "//pw_status",
        "//pw_system",
        "//pw_thread:thread",
        "//pw_thread_freertos:thread",
        "//pw_unit_test:rpc_service",
    ],
    alwayslink = True,
)

# This is just a stub to silence warnings saying that boot.cc and *.h files are
# missing from the bazel build. There's no plans yet to do a Bazel build for
# the Pi Pico.
filegroup(
    name = "rp2040_files",
    srcs = [
        "config/rp2040_hal_config.h",
    ],
)

# This is a duplication of the contents of pigweed_module_config.h since we
# can't do a -include because copts do not propagate to dependencies.
cc_library(
    name = "pigweed_module_config",
    hdrs = ["config/pigweed_module_config.h"],
    defines = [
        # LINT.IfChange
        "PW_THREAD_FREERTOS_CONFIG_JOINING_ENABLED=1",
        "PW_ASSERT_BASIC_ACTION=PW_ASSERT_BASIC_ACTION_EXIT",
        # LINT.ThenChange(//targets/rp2040/config/pigweed_module_config.h)
    ],
)

cc_library(
    name = "pre_init",
    srcs = [
        "boot.cc",
    ],
    target_compatible_with = [":freertos_config_cv"],
    deps = [
        ":extra_platform_libs",
        ":freertos_config",
        "//pw_cpu_exception:entry_backend_impl",
        "//pw_system:init",
        "//third_party/freertos:support",
        "@freertos",
        "@pico-sdk//src/rp2_common/hardware_exception:hardware_exception",
    ],
    alwayslink = 1,
)

cc_library(
    name = "device_handler",
    srcs = [
        "device_handler.cc",
    ],
    strip_include_prefix = "public",
    deps = [
        "//pw_cpu_exception_cortex_m:snapshot",
        "//pw_system:device_handler.facade",
        "//pw_thread_freertos:snapshot",
        "@pico-sdk//src/rp2_common/hardware_watchdog:hardware_watchdog",
    ],
)

pw_cc_binary(
    name = "system_async_example",
    testonly = True,
    srcs = ["system_async_example.cc"],
    # TODO(b/365184562): This target does not build with asan and fuzztest.
    target_compatible_with = select({
        "//pw_fuzzer:use_fuzztest": ["@platforms//:incompatible"],
        "//conditions:default": [],
    }),
    deps = [
        "//pw_channel:rp2_stdio_channel",
        "//pw_libcxx",
        "//pw_multibuf:testing",
        "//pw_system:async",
        "//third_party/freertos:support",
        "@pico-sdk//src/rp2_common/pico_stdlib",
    ],
)

rp2040_binary(
    name = "rp2040_system_async_example",
    testonly = True,
    binary = ":system_async_example",
)

flash_rp2040(
    name = "flash_rp2040_system_async_example",
    testonly = True,
    rp2040_binary = ":rp2040_system_async_example",
)

pw_copy_and_patch_file(
    name = "rp2040_memmap_default",
    src = "@pico-sdk//src/rp2_common/pico_crt0/rp2040:memmap_default.ld",
    out = "patched_rp2040_memmap_default.ld",
    patch_file = "patches/rp2040_memmap_default.ld.patch",
)

cc_library(
    name = "rp2040_linker_script",
    additional_linker_inputs = [":rp2040_memmap_default"],
    linkopts = ["-T$(execpath :rp2040_memmap_default)"],
    deps = [
        "@pico-sdk//src/rp2_common/pico_standard_link:default_flash_region",
    ],
)

rp2350_binary(
    name = "rp2350_system_async_example",
    testonly = True,
    binary = ":system_async_example",
)

flash_rp2350(
    name = "flash_rp2350_system_async_example",
    testonly = True,
    rp2350_binary = ":rp2350_system_async_example",
)

pw_copy_and_patch_file(
    name = "rp2350_memmap_default",
    src = "@pico-sdk//src/rp2_common/pico_crt0/rp2350:memmap_default.ld",
    out = "patched_rp2350_memmap_default.ld",
    patch_file = "patches/rp2350_memmap_default.ld.patch",
)

cc_library(
    name = "rp2350_linker_script",
    additional_linker_inputs = [":rp2350_memmap_default"],
    linkopts = ["-T$(execpath :rp2350_memmap_default)"],
    deps = [
        "@pico-sdk//src/rp2_common/pico_standard_link:default_flash_region",
    ],
)

sphinx_docs_library(
    name = "docs",
    srcs = [
        "49-pico.rules",
        "target_docs.rst",
        "upstream.rst",
    ],
    target_compatible_with = incompatible_with_mcu(),
)

filegroup(
    name = "bloaty_config",
    srcs = ["bloaty_config.bloaty"],
)
